package com.easyOrder.core.json.probe;

import com.easyOrder.core.exception.api.ArgumentsIncorrectException;
import com.easyOrder.core.utils.NameUtil;
import com.easyOrder.core.utils.TypeUtil;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

public class ProbeInfo {
	public static final String GetterPrefix = "get";

	public static final String SetterPrefix = "set";

	private Class<?> type;

	private Hashtable<String, Property> properties;

	public ProbeInfo(Class<?> type) {
		this.type = type;
		internalGetMembers();
	}

	public Property getProperty(String name) {
		return getProperty(name, true);
	}

	public Property getProperty(String name, boolean throwException) {
		Property property = properties.get(name);
		if ((null == property) && throwException) {
			throw new ArgumentsIncorrectException();
		}
		return property;
	}

	public Iterator<Map.Entry<String, Property>> getPropertyIterator() {
		return properties.entrySet().iterator();
	}

	private void internalGetMembers() {
		Method[] methods = type.getMethods();
		ArrayList<Method> getters = new ArrayList<Method>();
		Hashtable<String, Method> setters = new Hashtable<String, Method>();
		properties = new Hashtable<String, Property>();
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			String methodName = method.getName();
			if (!Modifier.isStatic(method.getModifiers())
					&& (method.getDeclaringClass() != Object.class)) {
				if ((method.getParameterTypes().length == 0)
						&& (method.getReturnType() != void.class)
						&& methodName.startsWith(GetterPrefix)) {
					if (!method.isBridge()) {
						getters.add(method);
					}
				} else if ((method.getParameterTypes().length == 1)
						&& (method.getReturnType() == void.class)
						&& (methodName.startsWith(SetterPrefix))) {
					setters.put(methodName, method);
				}
			}
		}

		int getterCount = getters.size();
		for (int i = 0; i < getterCount; i++) {
			Method getter = getters.get(i);
			Class<?> memberType = getter.getReturnType();
			String memberName = StringUtils.substring(getter.getName(),
					GetterPrefix.length());
			String camelMemberName = NameUtil.toCamel(memberName);
			Method setter = setters.get(SetterPrefix + memberName);
			if ((null != setter) || !TypeUtil.isStringable(memberType)) {
				properties.put(camelMemberName, new Property(getter, setter));
			}
		}
	}
}
